package net.xo68.destiny.core.discovery;

import lombok.extern.slf4j.Slf4j;
import net.xo68.destiny.contract.common.SystemConstants;
import net.xo68.destiny.contract.domain.node.NodeRegistry;
import net.xo68.destiny.core.util.ThreadUtils;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.SmartInitializingSingleton;

import java.util.Collection;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 节点注册发现监听者
 * @author wuxie
 * @version 2020-11-18
 */
@Slf4j
public class NodeDiscoveryClient implements SmartInitializingSingleton, DisposableBean,Runnable {

    private final AtomicBoolean started=new AtomicBoolean(false);

    private final NodeMapStore nodeMapStore;

    private final NodeDiscoveryRunner nodeDiscoveryRunner;

    private final ScheduledExecutorService scheduledExecutorService;

    private final long delay;

    public NodeDiscoveryClient(NodeDiscoveryRunner nodeDiscoveryRunner, long delay) {
        this.nodeMapStore = new NodeMapStore();
        this.nodeDiscoveryRunner=nodeDiscoveryRunner;
        this.delay=delay;
        this.scheduledExecutorService= ThreadUtils.newSingleThreadScheduled("discovery");
    }

    public void start(){
        if(started.compareAndSet(false,true)){
            //启动定时同时节点注册信息
            this.scheduledExecutorService.submit(new Runnable() {
                @Override
                public void run() {
                    nodeDiscoveryRunner.startLoad(nodeMapStore);
                }
            });
            this.scheduledExecutorService.scheduleWithFixedDelay(this, SystemConstants.INITIAL_DELAY_SECOND,this.delay, TimeUnit.SECONDS);
        }
    }


    @Override
    public void destroy() throws Exception {
        if(started.compareAndSet(true,false)){
            this.nodeDiscoveryRunner.downline(nodeMapStore);
            this.scheduledExecutorService.shutdown();
            log.info("NodeDiscoveryClient shutdown");
        }
    }

    @Override
    public void afterSingletonsInstantiated() {
        start();
    }

    @Override
    public void run() {
        if(started.get()){
            this.nodeDiscoveryRunner.execute(nodeMapStore);
        }
    }

    /**
     * 添加管理节点
     * @param nodeRegistry
     */
    public void addManageNode(NodeRegistry nodeRegistry){
        nodeMapStore.addManageNode(nodeRegistry);
    }

    /**
     * 添加工作节点
     * @param nodeRegistry
     */
    public void addWorkNode(NodeRegistry nodeRegistry){
        nodeMapStore.addWorkNode(nodeRegistry);
    }
    /**
     * 移除工作节点
     * @param nodeRegistry
     */
    public void removeWorkNode(NodeRegistry nodeRegistry){
        nodeMapStore.removeWorkNode(nodeRegistry);
    }

    /**
     * 管理节点
     * @return
     */
    public Collection<NodeRegistry> getManageNodes(){
        return nodeMapStore.getManageNodes();
    }
    /**
     * 返回管理节点host
     * @return
     */
    public List<String> getManageHosts(){
        return nodeMapStore.getManageHosts();
    }

    /**
     * 指定分组的工作节点
     * @param workGroupName
     * @return
     */
    public Collection<NodeRegistry> getWorkNodesByGroupName(final String workGroupName){
        return nodeMapStore.getWorkNodesByGroupName(workGroupName);
    }
    /**
     * 指定工作组的工作节点host
     * @param workGroupName
     * @return
     */
    public List<String> getWorkHostsByGroupName(final String workGroupName){
        return nodeMapStore.getWorkHostsByGroupName(workGroupName);
    }
}
